package com.bobi.tfca.network

import android.content.Context
import com.bobi.tfca.util.LogUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit


private var tfcaAuthorizationState: AuthorizationState = Unauthorized

class RequestBuilder(context: Context) {
    private var retrofitBuilder: Retrofit



    init {
        OkHttpClient.Builder()
            // .cookieJar(PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(context)))
            .addInterceptor(RequestInterceptor)
            .connectTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .build()
            .apply {
                retrofitBuilder = Retrofit.Builder()
                    .baseUrl(RequestConfiguration.URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(this)
                    .build()
            }
    }

    fun authorization(token: String? = null) {
        tfcaAuthorizationState = when (token) {
            null -> Unauthorized
            else -> Authorized(token)
        }
        LogUtil.i("tfcaAuthorizationState------------$tfcaAuthorizationState")
    }



    /**
     * TODO 获取APi接口的实体请求类
     *
     * @param T
     * @param APIType
     * @return
     */
    fun <T> getAPI(APIType: Class<T>): T = retrofitBuilder.create(APIType)

    /**
     * TODO 获取响应
     *
     * @param T 响应类型
     * @param requestFun 请求函数
     * @return 返回flow根据emit的密封类的类型来判断网络请求状态
     */
    suspend fun <T> getResponse(requestFun: () -> Response<T>): Flow<ApiResponse<T>> =
        flow {
            emit(ApiResponse.Loading)
            try {
                with(requestFun()) {
                    if (isSuccessful) {
                        if (body() != null) ApiResponse.Success(body()!!) else ApiResponse.Error(
                            Exception("失败"),
                            "服务器异常"
                        )
                    // TODO 添加token过期回调，根据状态码，删除缓存以及token，个人界面等信息没有
                    } else {
                        ApiResponse.Error(Exception("${code()}"), "")
                    }.let {
                        emit(it)
                    }
                }
            } catch (e: Exception) {
                LogUtil.e(e.toString())
                emit(ApiResponse.Error(e, "网络请求失败"))
            }
        }.catch { e ->
            emit(ApiResponse.Error(e as Exception, "网络请求失败"))
        }.flowOn(Dispatchers.IO)
}

/**
 *  网络请求配置
 */
object RequestConfiguration {
    const val URL = "http://192.168.131.85:30000"
}

/**
 * 响应类
 *
 * @param T
 */
sealed class ApiResponse<out T> {
    data class Success<out T>(val data: T?) : ApiResponse<T>()
    data class Error(val exception: Exception, val errMsg: String) : ApiResponse<Nothing>()
    object Loading : ApiResponse<Nothing>()
}


private object RequestInterceptor : Interceptor {

    private const val AUTHORIZATION = "Authorization"

    override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
        return chain.request()
            .let(::addAuthorizationHeader)
            .let(chain::proceed)
    }

    private fun addAuthorizationHeader(
        request: Request,
        authorizationState: AuthorizationState = tfcaAuthorizationState
    ): Request = when (authorizationState) {
        is Authorized -> {
            request.newBuilder().headers(
                request.headers()
                    .newBuilder()
                    .add(AUTHORIZATION, authorizationState.token)
                    .build()
            )
                .build()
        }
        else -> {
            request.newBuilder().headers(
                request.headers()
                    .newBuilder()
//                    .add(AUTHORIZATION, "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiLmnY7mloflj5EiLCJqdGkiOiIxIn0.nr01nBj2Pr3wO1gWQXFph_xb7HQ1WD4SxUjnOsSZZ_HWOFHEFYFBztO-qMAZDsrmTiBnWvbfG4VD_AwmEUaBnZ8H66jJWk1ZZUT7Folmos_5AU2GNwXxcHwAqS8cMlvCkBZwjf0Ni-ekHNtZitsYTFZB1jLFvt_-vDicupyCfPFyDpErh8yAxSUbnXr_LlfSTxThF4dLxrtJ01KRrQPDvOhcFH1wF8x1wZ2RD2LsaS4sbVOcDHKtPKtQsGjX0oUm9Fk_gehhh0C8Cltgj_0kK-yZrvXNduuXyJ3-ZrvfpW3rcr7w76DohBT7qw6GDKNLzVBV6rrvIG9Fd1gyevLM3g")
                    .build()
            )
                .build()
        }
    }

}

sealed interface AuthorizationState

data class Authorized(val token: String) : AuthorizationState

object Unauthorized : AuthorizationState